/*-
 * Copyright (c) 2006 Vishal Patil <bsd.devil@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#ifndef _ISCSI_H_
#define _ISCSI_H_

#ifndef _KERNEL_
#include <stdint.h>
#endif 

#include <sys/types.h>

#define ISCSI_TEXT_NULL			'\0'
#define ISCSI_KEY_VALUE_SEPARATOR	'='
#define ISCSI_MAX_NAME_LEN		256
#define ISCSI_PORT			3260
#define ISCSI_DEFAULT_TTT		0xffffffff

/* 
 * Opcode encoding bits 
 */
#define ISCSI_OP_RETRY			0x80
#define ISCSI_OP_IMMEDIATE		0x40
#define ISCSI_OPCODE_MASK		0x3F

/* 
 * Initiator Opcodes 
 */
#define ISCSI_NOP_OUT           0x00
#define ISCSI_SCSI_CMD          0x01
#define ISCSI_TASK_CMD          0x02
#define ISCSI_LOGIN_CMD         0x03
#define ISCSI_TEXT_CMD          0x04
#define ISCSI_WRITE_DATA        0x05
#define ISCSI_LOGOUT_CMD        0x06
#define ISCSI_SNACK             0x10

/* 
 * Target Opcodes 
 */
#define ISCSI_NOP_IN            0x20
#define ISCSI_SCSI_RSP          0x21
#define ISCSI_TASK_RSP          0x22
#define ISCSI_LOGIN_RSP         0x23
#define ISCSI_TEXT_RSP          0x24
#define ISCSI_READ_DATA         0x25
#define ISCSI_LOGOUT_RSP        0x26
#define ISCSI_R2T               0x31
#define ISCSI_ASYNC             0x32
#define ISCSI_REJECT            0x3f

/* 
 * This forms the BHS i.e. the Basic Header
 * Segment. The size for BHS is 44 bytes 
 */
struct iscsi_bhs {
	uint8_t 	opcode;
	uint8_t 	flags;			/* Final bit */
	uint8_t 	rsvd2[2];
	uint8_t 	hlength;		/* AHSs total length */
	uint8_t 	dlength[3];		/* Data length */
	uint8_t 	lun[8];			/* 64-bit lun id*/
	uint32_t 	itt;
	uint8_t 	other[28];
};

/*
 * This defines the iSCSI AHS i.e the Additional Header Segment
 */
struct iscsi_ahs {
	uint16_t 	hlength;		/* AHS length	*/
	uint8_t 	type;			/* Type		*/
	uint8_t		specific;		/* AHS Specific	*/
	char		data[0];
};


/* 
 * SCSI Command Header 
 */
struct iscsi_scsi_cmd_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	rsvd2;
	uint8_t 	cmdrn;
	uint8_t 	hlength;
	uint8_t 	dlength[3];
	uint8_t 	lun[8];
	uint32_t 	itt;
	uint32_t 	data_length;
	uint32_t 	cmdsn;
	uint32_t 	expstatsn;
	uint8_t 	scb[16];		/* SCSI Command Block */
	/* Additional Data (Command Dependent) */
};

/* 
 * Command PDU flags 
 */
#define ISCSI_FLAG_CMD_READ		0x40
#define ISCSI_FLAG_CMD_WRITE		0x20
#define ISCSI_FLAG_CMD_ATTR_MASK	0x07	/* 3 bits */

/* 
 * SCSI Command Attribute values 
 */
#define ISCSI_ATTR_UNTAGGED		0
#define ISCSI_ATTR_SIMPLE		1
#define ISCSI_ATTR_ORDERED		2
#define ISCSI_ATTR_HEAD_OF_QUEUE	3
#define ISCSI_ATTR_ACA			4

/* 
 * SCSI Response Header 
 */
struct iscsi_scsi_rsp_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	response;
	uint8_t 	cmd_status;
	uint8_t 	hlength;
	uint8_t 	dlength[3];
	uint8_t 	rsvd[8];
	uint32_t 	itt;
	uint32_t 	rsvd1;
	uint32_t 	statsn;
	uint32_t 	expcmdsn;
	uint32_t 	maxcmdsn;
	uint32_t 	expdatasn;
	uint32_t 	bi_residual_count;
	uint32_t 	residual_count;
	/* Response or Sense Data (optional) */
};

/* 
 * Command Response PDU flags 
 */
#define ISCSI_FLAG_CMD_BIDI_OVERFLOW	0x10
#define ISCSI_FLAG_CMD_BIDI_UNDERFLOW	0x08
#define ISCSI_FLAG_CMD_OVERFLOW 	0x04
#define ISCSI_FLAG_CMD_UNDERFLOW	0x02

/* 
 * iSCSI Status values. Valid if Rsp Selector bit is not set 
 */
#define ISCSI_STATUS_CMD_COMPLETED	0
#define ISCSI_STATUS_TARGET_FAILURE	1
#define ISCSI_STATUS_SUBSYS_FAILURE	2

/* 
 * Asynchronous Message Header 
 */
struct iscsi_async_msg_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	rsvd2[2];
	uint8_t 	rsvd3;
	uint8_t 	dlength[3];
	uint8_t 	lun[8];
	uint8_t 	rsvd4[8];
	uint32_t 	statsn;
	uint32_t 	expcmdsn;
	uint32_t 	maxcmdsn;
	uint8_t 	async_event;
	uint8_t 	async_vcode;
	uint16_t 	param1;
	uint16_t 	param2;
	uint16_t 	param3;
	uint8_t 	rsvd5[4];
};

/* 
 * iSCSI Event Codes 
 */
#define ISCSI_ASYNC_MSG_SCSI_EVENT			0
#define ISCSI_ASYNC_MSG_REQUEST_LOGOUT			1
#define ISCSI_ASYNC_MSG_DROPPING_CONNECTION		2
#define ISCSI_ASYNC_MSG_DROPPING_ALL_CONNECTIONS	3
#define ISCSI_ASYNC_MSG_PARAM_NEGOTIATION		4
#define ISCSI_ASYNC_MSG_VENDOR_SPECIFIC 		255

/* 
 * NOP-Out 
 */
struct iscsi_nop_out_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint16_t 	rsvd2;
	uint8_t		rsvd3;
	uint8_t 	dlength[3];
	uint8_t 	lun[8];
	uint32_t 	itt;
	uint32_t 	ttt;
	uint32_t 	cmdsn;
	uint32_t 	expstatsn;
	uint8_t 	rsvd4[16];
};

/* 
 * NOP-In 
 */
struct iscsi_nop_in_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint16_t 	rsvd2;
	uint8_t 	rsvd3;
	uint8_t 	dlength[3];
	uint8_t 	lun[8];
	uint32_t 	itt;
	uint32_t 	ttt;
	uint32_t 	statsn;
	uint32_t 	expcmdsn;
	uint32_t 	maxcmdsn;
	uint8_t 	rsvd4[12];
};

/* 
 * SCSI Task Management Request Header 
 */
struct iscsi_scsi_task_mgmt_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	rsvd1[2];
	uint8_t 	hlength;
	uint8_t 	dlength[3];
	uint8_t 	lun[8];
	uint32_t 	itt;
	uint32_t 	rtt;
	uint32_t 	cmdsn;
	uint32_t 	expstatsn;
	uint32_t 	refcmdsn;
	uint32_t 	expdatasn;
	uint8_t 	rsvd2[8];
};

#define ISCSI_FLAG_TMF_MASK		0x7F

/* 
 * Function values 
 */
#define ISCSI_TMF_ABORT_TASK		1
#define ISCSI_TMF_ABORT_TASK_SET	2
#define ISCSI_TMF_CLEAR_ACA		3
#define ISCSI_TMF_CLEAR_TASK_SET	4
#define ISCSI_TMF_LOGICAL_UNIT_RESET	5
#define ISCSI_TMF_TARGET_WARM_RESET	6
#define ISCSI_TMF_TARGET_COLD_RESET	7
#define ISCSI_TMF_TASK_REASSIGN 	8

/* 
 * SCSI Task Management Response Header 
 */
struct iscsi_scsi_task_mgmt_rsp_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	response;		/* see Response values below */
	uint8_t 	qualifier;
	uint8_t 	hlength;
	uint8_t 	dlength[3];
	uint8_t 	rsvd2[8];
	uint32_t 	itt;
	uint32_t 	rtt;
	uint32_t 	statsn;
	uint32_t 	expcmdsn;
	uint32_t 	maxcmdsn;
	uint8_t 	rsvd3[12];
};

/* 
 * Response values 
 */
#define ISCSI_TMF_RESP_COMPLETE 	0x00
#define ISCSI_TMF_RESP_UNKNOWN_TASK	0x01
#define ISCSI_TMF_RESP_UNKNOWN_LUN	0x02
#define ISCSI_TMF_RESP_TASK_ALLEGIANT	0x03
#define ISCSI_TMF_RESP_NO_FAILOVER	0x04
#define ISCSI_TMF_RESP_IN_PRGRESS	0x05
#define ISCSI_TMF_RESP_REJECTED 	0xff

/* 
 * Ready To Transfer Header 
 */
struct iscsi_r2t_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t		rsvd2[2];
	uint8_t 	rsvd3[12];
	uint32_t 	itt;
	uint32_t 	ttt;
	uint32_t 	statsn;
	uint32_t 	expcmdsn;
	uint32_t 	maxcmdsn;
	uint32_t 	rttsn;
	uint32_t 	data_offset;
	uint32_t 	data_length;
};

/* 
 * SCSI Data Hdr 
 */
struct iscsi_data_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	rsvd2[2];
	uint8_t 	rsvd3;
	uint8_t 	dlength[3];
	uint8_t 	lun[8];
	uint32_t 	itt;
	uint32_t 	ttt;
	uint32_t 	rsvd4;
	uint32_t 	expstatsn;
	uint32_t 	rsvd5;
	uint32_t 	datasn;
	uint32_t 	offset;
	uint32_t 	rsvd6;
	/* Payload */
};

/* 
 * SCSI Data Response Hdr 
 */
struct iscsi_data_rsp_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	rsvd2;
	uint8_t 	cmd_status;
	uint8_t 	hlength;
	uint8_t 	dlength[3];
	uint8_t 	lun[8];
	uint32_t 	itt;
	uint32_t 	ttt;
	uint32_t 	statsn;
	uint32_t 	expcmdsn;
	uint32_t 	maxcmdsn;
	uint32_t 	datasn;
	uint32_t 	offset;
	uint32_t 	residual_count;
};

/* 
 * Data Response PDU flags 
 */
#define ISCSI_FLAG_DATA_ACK		0x40
#define ISCSI_FLAG_DATA_OVERFLOW	0x04
#define ISCSI_FLAG_DATA_UNDERFLOW	0x02
#define ISCSI_FLAG_DATA_STATUS		0x01

/* 
 * Text Header 
 */
struct iscsi_txt_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	rsvd2[2];
	uint8_t 	hlength;
	uint8_t 	dlength[3];
	uint8_t 	rsvd4[8];
	uint32_t 	itt;
	uint32_t 	ttt;
	uint32_t 	cmdsn;
	uint32_t 	expstatsn;
	uint8_t 	rsvd5[16];
	/* Text - key=value pairs */
};

#define ISCSI_FLAG_TEXT_FINAL		0x80
#define ISCSI_FLAG_TEXT_CONTINUE	0x40

/* 
 * Text Response Header 
 */
struct iscsi_txt_rsp_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	rsvd2[2];
	uint8_t 	hlength;
	uint8_t 	dlength[3];
	uint8_t 	rsvd4[8];
	uint32_t 	itt;
	uint32_t 	ttt;
	uint32_t 	statsn;
	uint32_t 	expcmdsn;
	uint32_t 	maxcmdsn;
	uint8_t 	rsvd5[12];
	/* Text Response - key:value pairs */
};

/* 
 * Login Header 
 */
struct iscsi_login_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	max_version;
	uint8_t 	min_version;
	uint8_t 	hlength;
	uint8_t 	dlength[3];
	uint8_t 	isid[6];
	uint16_t 	tsih;
	uint32_t 	itt;
	uint16_t 	cid;
	uint16_t 	rsvd3;
	uint32_t 	cmdsn;
	uint32_t 	expstatsn;
	uint8_t 	rsvd5[16];
};

/* 
 * Login PDU flags 
 */
#define ISCSI_FLAG_LOGIN_TRANSIT		0x80
#define ISCSI_FLAG_LOGIN_CONTINUE		0x40

/*
 *	CSG stands for current stage while NSG stands for Next Stage
 */
#define ISCSI_FLAG_LOGIN_SECNEGO	0x00 /* 2 bits */
#define ISCSI_FLAG_LOGIN_OPNEGO		0x01 /* 2 bits */	
#define ISCSI_FLAG_LOGIN_FULL		0x03 /* 2 bits */

#define ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK	0x0C	/* 2 bits */
#define ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK	0x03	/* 2 bits */

#define ISCSI_LOGIN_CURRENT_STAGE(flags) \
	((flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2)
#define ISCSI_LOGIN_NEXT_STAGE(flags) \
	(flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK)

/* 
 * Login Response Header 
 */
struct iscsi_login_rsp_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	max_version;
	uint8_t 	active_version;
	uint8_t 	hlength;
	uint8_t 	dlength[3];
	uint8_t 	isid[6];
	uint16_t 	tsih;
	uint32_t 	itt;
	uint32_t 	rsvd3;
	uint32_t 	statsn;
	uint32_t 	expcmdsn;
	uint32_t 	maxcmdsn;
	uint8_t 	status_class;	/* see Login RSP ststus classes below */
	uint8_t 	status_detail;	/* see Login RSP Status details below */
	uint8_t 	rsvd4[10];
};

/* 
 * Login stage (phase) codes for CSG, NSG 
 */
#define ISCSI_SECURITY_NEGOTIATION_STAGE	0
#define ISCSI_OP_PARMS_NEGOTIATION_STAGE	1
#define ISCSI_FULL_FEATURE_PHASE		3

/* 
 * Login Status response classes 
 */
#define ISCSI_STATUS_CLS_SUCCESS		0x00
#define ISCSI_STATUS_CLS_REDIRECT		0x01
#define ISCSI_STATUS_CLS_INITIATOR_ERR		0x02
#define ISCSI_STATUS_CLS_TARGET_ERR		0x03

/* 
 * Login Status response detail codes 
 * Class-0 (Success) 
 */
#define ISCSI_LOGIN_STATUS_ACCEPT		0x00

/* Class-1 (Redirection) */
#define ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP	0x01
#define ISCSI_LOGIN_STATUS_TGT_MOVED_PERM	0x02

/* Class-2 (Initiator Error) */
#define ISCSI_LOGIN_STATUS_INIT_ERR		0x00
#define ISCSI_LOGIN_STATUS_AUTH_FAILED		0x01
#define ISCSI_LOGIN_STATUS_TGT_FORBIDDEN	0x02
#define ISCSI_LOGIN_STATUS_TGT_NOT_FOUND	0x03
#define ISCSI_LOGIN_STATUS_TGT_REMOVED		0x04
#define ISCSI_LOGIN_STATUS_NO_VERSION		0x05
#define ISCSI_LOGIN_STATUS_ISID_ERROR		0x06
#define ISCSI_LOGIN_STATUS_MISSING_FIELDS	0x07
#define ISCSI_LOGIN_STATUS_CONN_ADD_FAILED	0x08
#define ISCSI_LOGIN_STATUS_NO_SESSION_TYPE	0x09
#define ISCSI_LOGIN_STATUS_NO_SESSION		0x0a
#define ISCSI_LOGIN_STATUS_INVALID_REQUEST	0x0b

/* 
 * Class-3 (Target Error) 
 */
#define ISCSI_LOGIN_STATUS_TARGET_ERROR 	0x00
#define ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE	0x01
#define ISCSI_LOGIN_STATUS_NO_RESOURCES 	0x02

/* 
 * Logout Header 
 */
struct iscsi_logout_hdr {
	uint8_t 	opcode;
	uint8_t 	reason;
	uint8_t 	rsvd1[2];
	uint8_t 	hlength;
	uint8_t 	dlength[3];
	uint8_t 	rsvd2[8];
	uint32_t 	itt;
	uint16_t 	cid;
	uint8_t 	rsvd3[2];
	uint32_t 	cmdsn;
	uint32_t 	expstatsn;
	uint8_t 	rsvd4[16];
};

/* 
 * Logout PDU flags 
 */
#define ISCSI_FLAG_LOGOUT_REASON_MASK		0x7F

/* 
 * logout reason_code values 
 */
#define ISCSI_LOGOUT_REASON_CLOSE_SESSION	0
#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION	1
#define ISCSI_LOGOUT_REASON_RECOVERY		2
#define ISCSI_LOGOUT_REASON_AEN_REQUEST 	3

/* 
 * Logout Response Header 
 */
struct iscsi_logout_rsp_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	response;		/* see Logout response values below */
	uint8_t 	rsvd2;
	uint8_t 	hlength;
	uint8_t		dlength[3];
	uint8_t 	rsvd3[8];
	uint32_t 	itt;
	uint32_t 	rsvd4;
	uint32_t 	statsn;
	uint32_t 	expcmdsn;
	uint32_t 	maxcmdsn;
	uint32_t 	rsvd5;
	uint16_t 	t2wait;
	uint16_t	t2retain;
	uint32_t 	rsvd6;
};

/*
 * Target logout opcode
 */
#define ISCSI_LOGOUT_TARGET_OPCODE		0x26

/* 
 * logout response status values 
 */
#define ISCSI_LOGOUT_SUCCESS			0
#define ISCSI_LOGOUT_CID_NOT_FOUND		1
#define ISCSI_LOGOUT_RECOVERY_UNSUPPORTED	2
#define ISCSI_LOGOUT_CLEANUP_FAILED		3

/* 
 * SNACK Header 
 */
struct iscsi_snack_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	rsvd2[14];
	uint32_t 	itt;
	uint32_t	begrun;
	uint32_t 	runlength;
	uint32_t	expstatsn;
	uint32_t 	rsvd3;
	uint32_t 	expdatasn;
	uint8_t 	rsvd6[8];
};

/* 
 * SNACK PDU flags 
 */
#define ISCSI_FLAG_SNACK_TYPE_MASK	0x0F	/* 4 bits */

/* 
 * Reject Header 
 */
struct iscsi_reject_hdr {
	uint8_t 	opcode;
	uint8_t 	flags;
	uint8_t 	reason;
	uint8_t 	rsvd2;
	uint8_t 	rsvd3;
	uint8_t 	dlength[3];
	uint8_t 	rsvd4[16];
	uint32_t 	statsn;
	uint32_t 	expcmdsn;
	uint32_t 	maxcmdsn;
	uint32_t 	datasn;
	uint8_t 	rsvd5[8];
	/* Text - Rejected hdr */
};

/* 
 * Reason for Reject 
 */
#define ISCSI_REJECT_RESERVED			1
#define ISCSI_REJECT_DATA_DIGEST_ERROR		2
#define ISCSI_REJECT_SNACK_REJECT		3
#define ISCSI_REJECT_ISCSI_PROTOCOL_ERROR	4
#define ISCSI_REJECT_CMD_NOT_SUPPORTED		5
#define ISCSI_REJECT_IMM_CMD_REJECT		6
#define ISCSI_REJECT_TASK_IN_PROGRESS		7
#define ISCSI_REJECT_INVALID_DATA_ACK		8
#define ISCSI_REJECT_INVALID_PDU_FIELD		9
#define ISCSI_REJECT_CANT_GENERATE_TTT		10
#define ISCSI_REJECT_NEGOTIATION_RESET		11
#define ISCSI_REJECT_WAITING_FOR_LOGOUT 	12


/*
 *	iSCSI header
 */
union iscsi_pdu_hdr {
	struct iscsi_bhs			bhs;
	struct iscsi_scsi_cmd_hdr		cmd_hdr;
	struct iscsi_scsi_rsp_hdr		rsp_hdr;
	struct iscsi_async_msg_hdr		async_msg_hdr;
	struct iscsi_nop_out_hdr		nop_out_hdr;
	struct iscsi_nop_in_hdr			nop_in_hdr;
	struct iscsi_scsi_task_mgmt_hdr		tsk_hdr;
	struct iscsi_scsi_task_mgmt_rsp_hdr	tsk_rsp_hdr;	
	struct iscsi_r2t_hdr			r2t_hdr;
	struct iscsi_data_hdr			data_hdr;
	struct iscsi_data_rsp_hdr		data_rsp_hdr;
	struct iscsi_txt_hdr			txt_hdr;
	struct iscsi_txt_rsp_hdr		txt_rsp_hdr;
	struct iscsi_login_hdr			login_hdr;
	struct iscsi_login_rsp_hdr		login_rsp_hdr;
	struct iscsi_logout_hdr			logout_hdr;
	struct iscsi_logout_rsp_hdr		logout_rsp_hdr;
	struct iscsi_snack_hdr			snack_hdr;
	struct iscsi_reject_hdr			reject_hdr;
};

/*
 * iSCSI PDU structure
 */
struct iscsi_pdu {
	union iscsi_pdu_hdr	pdu_hdr;
	struct iscsi_ahs * 	ahs;
	uint32_t	 	hdr_digest;
	uint8_t	*		data_seg;	
	uint32_t		data_digest;	
};
/*
 * In-core iSCSI PDU structure
 */
struct iscsi_pdu_incore {
	/* Used to point to the next pdu in the list */
	struct iscsi_pdu_incore * next;
	
	union iscsi_pdu_hdr	pdu_hdr;

	/* Not present in the PDU, used to store the memory allocated */
	uint32_t		hlength_max;		
	struct iscsi_ahs * 	ahs;
		
	uint32_t	 	hdr_digest;

	/* Not present in the PDU, used to store the memory allocated */
	uint32_t		dlength_max;	
	uint8_t	*		data_seg;

	uint32_t		data_digest;	
};


#endif
